#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <time.h>

#define ITER 25 //Numero de iteracoes que serao executadas

int main (int argc, char *argv[]) 
{
	//Variaveis usadas para calcular tempo levado pelo algoritmo
	clock_t t0;
	clock_t tf;

	//Declaracao das variaveis utilizadas durante as iteracoes
	mpf_t aN, aNP1;
	mpf_t bN, bNP1;
	mpf_t pN, pNP1;
	mpf_t aux;
	
	long i;
	
	//Abertura do arquivo onde sera armazenado o valor final calculado
	FILE *piFile = fopen("out_borweinSeq.txt","w+");
	if(piFile == NULL) 
	{
		return EXIT_FAILURE;
	}
	
	printf("Starting...\n");
	//Inicializa o cronometro
	t0 = clock();
	
	//Setar precisão (usar todas as 10 milhões de casas) e inicializar variaveis do metodo
	mpf_init2(aN, 40000000);
	mpf_init2(bN, 40000000);
	mpf_init2(pN, 40000000);
	mpf_init2(aux, 40000000);
	mpf_init2(aNP1, 40000000);
	mpf_init2(bNP1, 40000000);
	mpf_init2(pNP1, 40000000);

	//Inicializa as variaveis do algoritmo com os valores iniciais
	mpf_sqrt_ui(aux, 2); //a0 = 2^(1/2)
	mpf_set(aN, aux);
	mpf_set_ui(bN, 0); //b0 = 0
	mpf_add_ui(pN, aux, 2); //p0 = 2 + 2^(1/2) 
	
	//Loop principal
	for(i = 0 ; i<ITER ; i++) 
	{   
		//Calculo das variaveis de an+1, bn+1 e pn+1
		mpf_sqrt(aux, aN);
		mpf_ui_div(aNP1, 1, aux);
		mpf_add(aNP1, aNP1, aux);
		mpf_div_ui(aNP1, aNP1, 2); //an+1
		
		mpf_add_ui(bNP1, bN, 1);
		mpf_mul(bNP1, bNP1, aux);
		mpf_add(aux, aN, bN);
		mpf_div(bNP1, bNP1, aux); //bn+1
		
		mpf_add_ui(pNP1, aNP1, 1);
		mpf_mul(pNP1, pNP1, pN);
		mpf_mul(pNP1, bNP1, pNP1);
		mpf_add_ui(aux, bNP1, 1);
		mpf_div(pNP1, pNP1, aux); //pn+1

		//Swap das variaveis
		mpf_set(aN,aNP1);
		mpf_set(bN,bNP1);
		mpf_set(pN,pNP1);
	}

	//Finaliza o cronometro e mostra o tempo de execucao do programa
	tf = clock();
	printf("\nExecution: %lf s\nNumber of Iterations: %ld\n",(double)((tf - t0)/CLOCKS_PER_SEC),i);

	//Escreve no arquivo o valor calculado de pi
	mpf_out_str(piFile,10,250000,pNP1);
	
	//Fecha o arquivo e limpa as variaveis do algoritmo
	fclose(piFile);
	mpf_clears(aN,bN,pN,aNP1,bNP1,pNP1,NULL);
}
